---
--类名: NpcFactory.lua
--创建日期: 2017-3-20
--创建人: 陈小虎
--功能描述:
--修改内容:
--修改日期:
--修改人: galileoliu
--修改备注:
--
local Npc = import("..models.Npc")
local Area = import("..models.Area")

local NpcFactory = class("NpcFactory")

function NpcFactory:ctor()

end

function NpcFactory:setNpcParent(parent)
	self._npcParent = parent
end

function NpcFactory:getNpcParent()
	return self._npcParent
end

function NpcFactory:createNpc(npcConfig,uid,loading,public,async,dstPos,displayId)
    if not npcConfig or not npcConfig.ID or not uid then return end

    local function npcUpHeadStatus(npc)
        if not npc then return end
        if NpcManager:isStopUpdateNpcsEvent() and not loading then
            npc:allNameNodeVisibility(false)
            npc:currentMarkVisibility(false)
            npc:stopShowUpHead(true)
        else
            npc:allNameNodeVisibility(true)
            npc:currentMarkVisibility(true)
            npc:stopShowUpHead(false)
        end
        npc:resetMarkFromEvent()
    end

    local npcId = tonumber(npcConfig.ID)
    local showModel = npcConfig.showModel and tonumber(npcConfig.showModel) or 0
    local x = dstPos or npcConfig.coordinate and tonumber(npcConfig.coordinate) or 0
    local line = npcConfig.setFloor and tonumber(npcConfig.setFloor) or 2
    local zOrder = npcConfig.zOrder and tonumber(npcConfig.zOrder) or 0
--    local uiHideType = npcConfig.uihiddentype and tonumber(npcConfig.uihiddentype) or 0
    local battleOrder = npcConfig.battleOrScriptOrder and tonumber(npcConfig.battleOrScriptOrder) or 0
    local name = npcConfig.name and L(npcConfig.name) or ""
    local title = npcConfig.title and L(npcConfig.title) or ""
    local map
    if not loading then
        map = self:getNpcParent()
    end

    if showModel == 0 then
        local npcExisted
        if map then
            npcExisted = NpcManager:getNpcByUid(uid)
        end

        if not npcExisted then
            local npc = Npc.new(npcId,async,displayId)
            local lx,rx,nx,radius,talkRadius,tlx,trx = NpcManager:getHintTriggerRangeToNpc(npc:getId(), x)
            npc:setEventRange(lx,rx,nx,radius,talkRadius,tlx,trx)
--                npc:setUiHideType(uiHideType)
            npc:setNameText(name)
            npc:setTitleText(title)
            if tonumber(npcConfig.headTagShow) ~= 0 then
                npc:setShowName(true)
            else
                npc:setShowName(false)
            end

            npc:setUid(uid)
            npc:setSoundPath(npcConfig.npcSound)
            npc:setOriginalX(x)
--            npc:setMapType(npcConfig.mapType)
--            npc:setMapShow(npcConfig.mapshow)
--            npc:setMapListShow(npcConfig.maplistshow)
            npc:setVariety(tonumber(npcConfig.npcCategories))

            npc:setNameColor(Res.PlayerNameColors.Npc)
            npc:setZValue(zOrder)
            npc:setConfig(npcConfig)

            local speed = tonumber(npcConfig.defaultSpeed) or 400
            npc:setDefaultSpeed(speed)
            npc:setSpeed(speed)

            npc:setOffsetY(tonumber(npcConfig.offsetY) or 0)
            npc:setFaceTo(tonumber(npcConfig.faceto) or 0)
            npc:setBattleOrder(battleOrder)
            npc:setDefaultAction(npcConfig.defaultAction)
            npc:setCommonMark(npcConfig.commonSign)

            if npcConfig.styleAction then
                local action = string.split(npcConfig.styleAction,"|")
                if #action >= 3 then
                    npc:setStyleAction(action[1])
                    npc:setStyleMinSeconds(tonumber(action[2]))
                    npc:setStyleMaxSeconds(tonumber(action[3]))
                end
            end

            -- npc:setLinesData(MapManager:getLinesData())

            npc:setLine(line)
            npc:setDirection(tonumber(npcConfig.direction))
            npc:setOriginalDirection(tonumber(npcConfig.direction))
            if npcConfig.type then
                npc:setType(tonumber(npcConfig.type))
            end
            npc:showLocationX(x)
            npc:playDefaultAction()

            if loading or cc.isDead(map) then
                npc:retain()
                NpcManager:addLoadNpc(npc)
            else
                NpcManager:addNpc(npc)
                if map then
                    map:addNpcToLine(line,npc,zOrder)
--                    npc:setBubble(NodeFactory:createBubble())
                    npc:setNameNode(NodeFactory:createHeadName())
                    npc:setTitle(npc:getTitleText())
                    npc:setName(npc:getNameText())
                end
            end

            npc:setIntoSightCallback(function()
                -- 初始化NPC的功能脚本
                ScriptManager:updateNpcScripts(npc)
            end)

            npc:setOutSightCallback(function()

            end)

            npcUpHeadStatus(npc)
            return npc
        else
            npcExisted:showLocationX(x)
            npcExisted:clearEvents()
            npcUpHeadStatus(npcExisted)
            return npcExisted
        end

    elseif showModel == 1 then
        local area = Area.new(npcId, uid)
        area:setVariety(npcConfig.npcCategories and tonumber(npcConfig.npcCategories) or 1)
        area:setName(name)
        area:setPublic(public)
        area:setBattleOrder(battleOrder)
        NpcManager:addArea(area)
    end

    return nil
end

-- 进场景 或者 有主线任务更新时，创建所有主线任务控制的npc
function NpcFactory:createAllMainTaskNpc()
    local conf = GD:queryMapsetOpenTaskNpcs()
    local mapId = MapManager:getMapId()
    local mainTaskId = UD:getMainTaskId()

    for _, npc in ipairs(conf) do
        local needTaskId = tonumber(npc.openTask)
        local npcId = tonumber(npc.ID)
        local npcConf = GD:queryMapNpc(npcId)
        if tonumber(npcConf.mapId) == mapId and mainTaskId > needTaskId then
            local npcInfo = NpcManager:getNpcById(npcId)
            if not npcInfo then
                local npcUid = NpcManager:generateNpcUid()
                self:createNpc(npcConf, npcUid, nil, nil, true)
            end
        end
    end
end


-- 进场景时 创建所有活动npc
function NpcFactory:createAllActivityNpc()
    -- 世界boss
    local worldBossData = app:sendMsg("BossModel", "getWorldBossStatusData")
    if worldBossData and worldBossData.open then
        self:createActivityNpcById(Enums.activityNpcType.worldBoss, worldBossData.bossId)
    end
    -- 公会战
    self:createActivityNpcById(Enums.activityNpcType.dynasty)
end

-- 创建活动npc
function NpcFactory:createActivityNpcById(activityId, data)
    if activityId == Enums.activityNpcType.worldBoss then
        local npcId = GD:getWorldBossNpcId(app:getWeekDay(), MapManager:getMapId())
        if npcId then
            local npc = NpcManager:getNpcById(npcId)
            if not npc then
                local npcC = GD:queryMapNpc(npcId)
                local npcUid = NpcManager:generateNpcUid()
                local bossId = data
                self:createNpc(npcC, npcUid, nil, nil, true, nil, bossId)
                -- 暂时不判断创建失败的情况             
            end
        end
    elseif activityId == Enums.activityNpcType.dynasty then
        -- 查询当前场景中所有的领地
        local distictInfos = GD:queryWorldZoneConfs()
        for _, info in ipairs(distictInfos) do
            if tonumber(info.map) == MapManager:getMapId() then
                local npcId = tonumber(info.npcID)
                local npc = NpcManager:getNpcById(npcId)
                local status = app:sendMsg("DynastyBattleModel", "getPhaseByTownId", tonumber(info.ID))
                if status == "READY" or status == "FIGHT" then -- 添加NPC
                    -- print("add npc", npcId)
                    if not npc then 
                        -- print("add npc true!")
                        local npcC = GD:queryMapNpc(npcId)
                        local npcUid = NpcManager:generateNpcUid()
                        self:createNpc(npcC, npcUid, nil, nil, true, nil)
                    end
                else -- 移除NPC
                    -- print("delete npc", npcId)
                    if npc then
                        NpcManager:deleteNpcById(npcId)
                    end
                end
            end
        end
    end
end

-- 移除活动npc
function NpcFactory:deleteActivityNpc(activityId)
    if activityId == Enums.activityNpcType.worldBoss then -- 世界boss
        local npcId = GD:getWorldBossNpcId(app:getWeekDay(), MapManager:getMapId())
        if npcId then
            NpcManager:deleteNpcById(npcId)
        end
    end
end

function NpcFactory:createTaskNpcById(npcId,px,isAuto,taskId,isGather)
    local npcC = GD:queryMapNpc(npcId)
    if npcC == nil then
        print("Map npc config is nil!!!!!!!!!!!!!!!!!! ", npcId)
        return
    end
    if npcC.mapId ~= "" and tonumber(npcC.mapId) ~= MapManager:getMapId() then
        return
    end
    local npcUid = NpcManager:generateNpcUid()
    local npc = self:createNpc(npcC,npcUid,nil,nil,true)
    if npc then
--        npc:setAuto(isAuto)
        npc:setTaskId(taskId)
        npc:setGatherType(isGather)
        if px then
            npc:showLocationX(px)
        end
    else
        local area = NpcManager:getArea(npcId)
        if area then
            area:setTaskId(taskId)
            area:setCenterX(px)
        end
    end
end

function NpcFactory:createTaskBaseNpcs(dstMapId)
    local ids = TaskManager:getBaseNpcShowIds()
    local npcConfig
    local npcUid
    for _, npcId in pairs(ids) do
        npcConfig = GD:queryMapNpc(npcId)
        if npcConfig and tonumber(npcConfig.mapId) == tonumber(dstMapId) then
            npcUid = NpcManager:generateNpcUid()
--            print("================> NpcFactory:createTaskBaseNpcs()", npcUid, npcConfig.ID)
            self:createNpc(npcConfig,npcUid,true,nil,false)
        end
    end
end

function NpcFactory:createGrayBattleNpcs(dstMapId, loading)
    if not dstMapId then return end
    local grayBattleNpcs = UD:getGrayBattleNpcs()
    local grayBattleNpcUidList = {}
    if grayBattleNpcs then
        local npc
        for uid, grayBattleNpc in pairs(grayBattleNpcs) do
            if grayBattleNpc.mapId == dstMapId then
                npc = self:createNpc(grayBattleNpc.npcConfig, uid, loading, nil, false, grayBattleNpc.position)
                npc:setBattleId(grayBattleNpc.battleId)
                npc:setMineId(grayBattleNpc.mineId)
                npc:setMarkType("common")
                npc:setMark("taskBattle")
                table.insert(grayBattleNpcUidList, uid)
            end
        end
    end
    return grayBattleNpcUidList
end

function NpcFactory:createBNpc(npcConfig,async)
    if not npcConfig or not npcConfig.ID then return end
    local npcId = tonumber(npcConfig.ID)
    local npc = Npc.new(npcId,async)
    return npc
end

function NpcFactory:createMapBaseNpc(npcConfig,uid,dstMapId,loading,async)
    if DungeonManager:isDungeonNpc(npcConfig) then
        return
    end
    if npcConfig and tonumber(npcConfig.mapId) == dstMapId then
--        print("================> NpcFactory:createMapBaseNpc()", uid, npcConfig.ID)
        self:createNpc(npcConfig,uid,loading,nil,async)
    end
end

--function NpcFactory:createMapBaseNpcById(npcId)
--    local npcConfig = NpcManager:getNpcConfigById(npcId)
--    local npcUid = NpcManager:generateNpcUid()
--    self:createMapBaseNpc(npcConfig,npcUid,MapManager:getMapId(),nil,true)
--end

--function NpcFactory:createNpcFromMapset()
--    local configs = NpcManager:getMapsetBaseConfigs()
--    local npcUid
--    for _, npcConfig in pairs(configs) do
--        if npcConfig.modelShow and tonumber(npcConfig.modelShow) == 1 then
--            npcUid = NpcManager:generateNpcUid()
--            self:createMapBaseNpc(npcConfig,npcUid,MapManager:getMapId(),nil,true)
--        end
--    end
--end

function NpcFactory:createAllMapBaseNpc(dstMapId)
    if not dstMapId then return end
    local configs = GD:queryMapsetBaseByMapId(dstMapId)
    local npcUid
    for _, npcConfig in pairs(configs) do
        if not TaskManager:isBaseNpcHide(npcConfig.ID) and npcConfig.modelShow and tonumber(npcConfig.modelShow) == 1 then
            npcUid = NpcManager:generateNpcUid()
            self:createMapBaseNpc(npcConfig,npcUid,dstMapId,true,false)
        end
    end
end

function NpcFactory:createAllMapBaseNpcWithoutLimit(dstMapId)
    if not dstMapId then return end

    local configs = GD:queryMapsetBaseByMapId(dstMapId)
    local npcUid
    for _, npcConfig in pairs(configs) do
        if NpcManager:getNpcByTypeId(npcConfig.ID) == nil then
            npcUid = NpcManager:generateNpcUid()
            self:createMapBaseNpc(npcConfig,npcUid,dstMapId,false,false)
        end
    end
end

--function NpcFactory:createActivityNpc(npcId)
--    local npcConfig = NpcManager:getNpcConfigById(npcId)
--    local npcUid = NpcManager:generateNpcUid()
--    self:createNpc(npcConfig,npcUid,false,nil,true,false,true)
--end

function NpcFactory:createAllResourcePoints(dstMapId, loading)
    local npcResourcePoints = UD.npcResourcePoints
    local resourcePointNpcUidList = {}
    if npcResourcePoints then
        local npcConfig
        for _,v in pairs(npcResourcePoints) do
            npcConfig = GD:queryMapNpc(v.id)
            if npcConfig and tonumber(npcConfig.mapId) == tonumber(dstMapId) then
                local npcUid = NpcManager:generateNpcUid()
                self:createNpc(npcConfig, npcUid, loading, nil, true)
                table.insert(resourcePointNpcUidList, npcUid)
            end
        end
    end
    return resourcePointNpcUidList
end

function NpcFactory:createRoastPointFromOre(dstMapId,loading)
    local configs
    if dstMapId then
        configs = GD:queryOreByMapIdAndType(dstMapId,3)
    else
        configs = NpcManager:getRoastConfigs()
    end
    if configs then
        local npcUid
        for _, npcConfig in pairs(configs) do
            npcUid = NpcManager:generateNpcUid()
            self:createNpc(npcConfig,npcUid,loading,nil,true)
        end
    end
end

--function NpcFactory:createNpcFromServiceInsert()
--    local npcConfig
--    for _,v in ipairs(NpcManager:getServiceInsertNpcs()) do
--        npcConfig = NpcManager:getNpcConfigById(v.tid)
--        if npcConfig and npcConfig.ID then
--            local function createNpc()
--                local ownerNpc = self:createNpc(npcConfig,v.uid,nil,nil,true)
--                if ownerNpc then
--                    if BattleManager:isBattle() then
--                        ownerNpc:setVisible(false)
--                    end
--                end
--            end
--            createNpc()
--        end
--    end
--    NpcManager:clearServiceInsertNpcs()
--end

function NpcFactory:createServiceInsertNpc(npc)
    local npcUid = npc.uid
    local npcId = npc.tid
    local npcConfig = NpcManager:getNpcConfigById(npcId)
    local ownerNpc
    if npcConfig and npcConfig.ID then
        ownerNpc = self:createNpc(npcConfig,npcUid,nil,nil,true)
        if ownerNpc then
            if BattleManager:isBattle() then
                ownerNpc:setVisible(false)
            end
        end
    end
    return ownerNpc
end

function NpcFactory:createDungeonNpcs(formations)
    if not formations then return end
    local npcConfig
    local npcUid
    for _,v in pairs(formations) do
        npcConfig = NpcManager:getNpcConfigById(v.npcId)
        npcUid = NpcManager:generateNpcUid()
        self:createNpc(npcConfig,npcUid,false,nil,true)
    end
end

--function NpcFactory:createDungeonNpcById(npcId)
--    local npcConfig = NpcManager:getNpcConfigById(npcId)
--    local npcUid = NpcManager:generateNpcUid()
--    return self:createNpc(npcConfig,npcUid,false,nil,true)
--end

function NpcFactory:addLoadNpcs()
    for _,npc in ipairs(NpcManager:getLoadNpcs()) do
        NpcManager:addNpc(npc)
        if self:getNpcParent() then
            local line = npc:getLine()
            self:getNpcParent():addNpcToLine(line,npc,npc:getZValue())

--            npc:setBubble(NodeFactory:createBubble())
            npc:setNameNode(NodeFactory:createHeadName())
            npc:setTitle(npc:getTitleText())
            npc:setName(npc:getNameText())
            npc:adjustPos(true)
        end
        npc:release()
    end
    NpcManager:clearLoadNpcs()
end

function NpcFactory:setGuildNpcTitles()
    local bcm = app:getInst("BiddingController").battleMapModel

    if not bcm then
        print("town list not ready")
        return
    end

    local distictInfos = GD:queryWorldZoneConfs()
    for _, info in ipairs(distictInfos) do
        local townID = checknumber(info.ID)
        if tonumber(info.map) == MapManager:getMapId() and bcm.hTownInfos[townID] then
            local npcs = info.includeNpcID
            if npcs and npcs:len() > 1 then
                local npcids = npcs:split(";")
                for i, v in pairs(npcids) do
                    local guildName = bcm.hTownInfos[townID]:getGuildName()
                    -- guildName = "TST"
                    local pnpc = NpcManager:getNpcByTypeId(checknumber(v))
                    if pnpc then
                        if guildName then
                            local titlename = string.format(L("townOwnerFlagNpcName"), guildName)
                            pnpc:setOwnerGuildName(titlename)
                        else
                            pnpc:setOwnerGuildName("")
                        end
                    end
                end
            end            
        end
    end
end

-- 创建插旗npc
function NpcFactory:createFlagNpc()
    local bcm = app:getInst("BiddingController").battleMapModel

    if not bcm then
        print("town list not ready")
        return
    end
    local distictInfos = GD:queryWorldZoneConfs()
    for _, info in ipairs(distictInfos) do
        local townID = checknumber(info.ID)
        if tonumber(info.map) == MapManager:getMapId() and bcm.hTownInfos[townID] then
            local npcId = tonumber(info.flagnpcID)
            local guildName = bcm.hTownInfos[townID]:getGuildName()
            if guildName then
                local finfo = bcm.hTownInfos[townID]:getFlagInfo()
                local npc = NpcManager:getNpcById(npcId)
                local npcC = GD:queryMapNpc(npcId)
                local flagCache = NpcManager._flagNpcs
                local npcUid = flagCache[npcId] or NpcManager:generateNpcUid()
                flagCache[npcId] = npcUid
                local npcobj = self:createNpc(npcC, npcUid, nil, nil, true, nil)
                -- local s = npcobj:getRootArmature():getSlot("body1")
                -- s:setDisplay(img, 0)
    
                npcobj:setName(string.format(L("townOwnerFlagNpcName"), guildName))
                npcobj:getRootArmature():getArmature():getBone("body1"):setVisible(false)
                npcobj:getRootArmature():getArmature():getBone("body2"):setVisible(false)
                local s = 0.3
                local uo = 66
                local bo = 40
                local c = cc.c3b( 255, 223, 123 )
                if checkbool(npcobj.imgLoaded) == false then
                    local img = ccui.ImageView:create(GD:getImagePath( Res.guildIconPath, finfo.flagBaseIcon ),0)
                    img:getVirtualRenderer():setColor(c)
            
                    img:setScale(s)
                    img:setAnchorPoint(cc.p(0.5, 1))
                    local pos = cc.p(npcobj:getRootArmature():getBoneLocalPos("body1"))
                    pos.y = pos.y - uo
                    img:setPosition(pos)
                    npcobj.mArmParent:addChild(img)
        
                    img = ccui.ImageView:create(GD:getImagePath( Res.guildIconPath, finfo.flagAdditionalIcon ),0)
                    img:getVirtualRenderer():setColor(c)
                    img:setScale(s)
                    img:setAnchorPoint(cc.p(0.5, 1))
                    pos = cc.p(npcobj:getRootArmature():getBoneLocalPos("body2"))
                    pos.y = pos.y - bo
                    img:setPosition(pos)
                    npcobj.mArmParent:addChild(img)
                    npcobj.imgLoaded = true
                end
            else
                self:deleteFlagNpc(npcId)
            end
        end
    end
end

-- 移除插旗npc
function NpcFactory:deleteFlagNpc(npcId)
    NpcManager:deleteNpcById(npcId)
end

return NpcFactory
